/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <test_utilities/test_base.h>
#include <mc/common.h>
#include <mc/memory.h>
#include <vector>
#include <memory>
#include <string>

#include "../../../../drivers/internal/chip/chip_ads78/ads78.h"
#include "../../../../drivers/internal/bus/bus_base/bus.h"
#include "../../../../drivers/internal/hasdef.h"

using namespace dev;

namespace {
// Mock bus_base 用于测试
class mock_bus : public bus_base {
public:
    mock_bus() : bus_base(), m_read_result(HAS_OK), m_write_result(HAS_OK) {
    }

    void set_read_result(uint32_t result) {
        m_read_result = result;
    }

    void set_write_result(uint32_t result) {
        m_write_result = result;
    }

    void set_read_data(const std::vector<uint8_t>& data) {
        m_read_data = data;
    }

    uint32_t read(ACCESS_DATA_S& input) override {
        if (m_read_result == HAS_OK) {
            input.out_buffer = m_read_data;
        }
        return m_read_result;
    }

    uint32_t write(ACCESS_DATA_S& input) override {
        return m_write_result;
    }

    uint8_t get_id() override {
        return 1;
    }

    void bus_lock() override {
    }

    void bus_unlock() override {
    }

private:
    uint32_t m_read_result;
    uint32_t m_write_result;
    std::vector<uint8_t> m_read_data;
};

// Test fixture
class ads78_test : public mc::test::TestWithEngine {
protected:
    void SetUp() override {
        TestWithEngine::SetUp();
        m_chip = std::make_shared<chip_ads78>();
        m_bus = std::make_shared<mock_bus>();
    }

    void TearDown() override {
        m_chip.reset();
        m_bus.reset();
        TestWithEngine::TearDown();
    }

    mc::mutable_dict create_csr() {
        mc::mutable_dict csr;
        csr["Address"] = static_cast<uint32_t>(0x48);
        csr["OffsetWidth"] = static_cast<uint8_t>(1);
        csr["AddrWidth"] = static_cast<uint8_t>(1);
        csr["WriteTmout"] = static_cast<uint32_t>(100);
        csr["ReadTmout"] = static_cast<uint32_t>(100);
        csr["RwBlockSize"] = static_cast<uint8_t>(2);
        csr["WriteInterval"] = static_cast<uint8_t>(1);
        csr["ReadInterval"] = static_cast<uint8_t>(1);
        csr["WriteRetryTimes"] = static_cast<uint8_t>(3);
        csr["ReadRetryTimes"] = static_cast<uint8_t>(3);
        return csr;
    }

    std::shared_ptr<chip_ads78> m_chip;
    std::shared_ptr<mock_bus> m_bus;
};

// 注意：get_register_address 和 convert_adc_to_millivolts 是私有方法，
// 无法直接测试，但可以通过 bit_read 方法间接测试它们的功能

// ========== init 测试 ==========

TEST_F(ads78_test, init_success) {
    auto csr = create_csr();
    bool result = m_chip->init(csr);
    EXPECT_TRUE(result);
}

TEST_F(ads78_test, init_with_minimal_csr) {
    // 测试最小CSR配置
    mc::mutable_dict csr;
    csr["Address"] = static_cast<uint32_t>(0x48);
    csr["OffsetWidth"] = static_cast<uint8_t>(1);
    csr["AddrWidth"] = static_cast<uint8_t>(1);
    csr["WriteTmout"] = static_cast<uint32_t>(100);
    csr["ReadTmout"] = static_cast<uint32_t>(100);
    
    bool result = m_chip->init(csr);
    EXPECT_TRUE(result);
}

// ========== bit_read 测试 ==========

TEST_F(ads78_test, bit_read_success_channel_0) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回的数据
    // 模拟ADC值：高4位为0x0，低8位为0x80 (128)
    // 原始ADC值 = (0x0 & 0xf) << 8 | 0x80 = 128
    // 转换后的电压 = 128 * 2500 / 4096 = 78.125 ≈ 78 mV
    // 78 mV = 0x004E (小端序：低字节在前)
    std::vector<uint8_t> read_data = {0x00, 0x80};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 2);
    // 78 mV = 0x004E (高字节在前，低字节在后)
    // out_buffer[0] = (78 >> 8) & 0xFF = 0x00
    // out_buffer[1] = 78 & 0xFF = 0x4E
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0x00);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[1]), 0x4E);
}

TEST_F(ads78_test, bit_read_success_channel_7) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回的数据
    // 注意：代码使用 out_buffer[0] & 0xf 提取低4位，而不是高4位
    // 所以要表示高4位为0x1，低8位为0x00的ADC值，应该使用 {0x01, 0x00}
    // 原始ADC值 = (0x01 & 0xf) << 8 | 0x00 = 256
    // 转换后的电压 = 256 * 2500 / 4096 = 156.25，转换为uint16_t = 156 mV
    // 156 mV = 0x009C (高字节在前，低字节在后)
    std::vector<uint8_t> read_data = {0x01, 0x00};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(7, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 2);
    // 156 mV = 0x009C (高字节在前，低字节在后)
    // out_buffer[0] = (156 >> 8) & 0xFF = 0x00
    // out_buffer[1] = 156 & 0xFF = 0x9C
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0x00);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[1]), 0x9C);
}

TEST_F(ads78_test, bit_read_invalid_channel) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    // 测试无效通道（超过最大值）
    int32_t result = m_chip->bit_read(8, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("invalid channel offset") != std::string::npos);
}

TEST_F(ads78_test, bit_read_no_bus) {
    // 初始化芯片但不设置bus
    auto csr = create_csr();
    m_chip->init(csr);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    // 测试没有bus的情况，应该抛出异常
    EXPECT_THROW(
        {
            m_chip->bit_read(0, 2, 0, in_buffer, out_buffer, error);
        },
        mc::invalid_op_exception);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("pre bus object not found") != std::string::npos);
}

TEST_F(ads78_test, bit_read_bus_read_failure) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回错误
    m_bus->set_read_result(HAS_ERR);
    m_bus->set_read_data({});

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("read operation failed") != std::string::npos);
}

TEST_F(ads78_test, bit_read_insufficient_data) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 设置mock bus返回的数据不足
    std::vector<uint8_t> read_data = {0x00};  // 只有1字节，需要2字节
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_ERR);
    EXPECT_FALSE(error.empty());
    EXPECT_TRUE(error.find("insufficient data received") != std::string::npos);
}

TEST_F(ads78_test, bit_read_full_range_adc_value) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 测试最大ADC值：高4位为0xF，低8位为0xFF
    // 原始ADC值 = (0xF & 0xf) << 8 | 0xFF = 4095
    // 转换后的电压 = 4095 * 2500 / 4096 = 2499.389...，转换为uint16_t = 2499 mV
    // 2499 mV = 0x09C3 (高字节在前，低字节在后)
    std::vector<uint8_t> read_data = {0xFF, 0xFF};
    m_bus->set_read_data(read_data);
    m_bus->set_read_result(HAS_OK);

    std::vector<uint8_t> in_buffer;
    std::vector<uint8_t> out_buffer;
    std::string error;

    int32_t result = m_chip->bit_read(0, 2, 0, in_buffer, out_buffer, error);
    EXPECT_EQ(result, HAS_OK);
    EXPECT_TRUE(error.empty());
    EXPECT_EQ(out_buffer.size(), 2);
    // 2499 mV = 0x09C3 (高字节在前，低字节在后)
    // out_buffer[0] = (2499 >> 8) & 0xFF = 0x09
    // out_buffer[1] = 2499 & 0xFF = 0xC3
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[0]), 0x09);
    EXPECT_EQ(static_cast<uint8_t>(out_buffer[1]), 0xC3);
}

TEST_F(ads78_test, bit_read_all_channels) {
    // 初始化芯片
    auto csr = create_csr();
    m_chip->init(csr);
    m_chip->set_left_bus(m_bus);
    m_chip->set_host_bus(m_bus);

    // 测试所有通道都能正常读取
    for (uint32_t channel = 0; channel <= 7; ++channel) {
        // 为每个通道设置不同的ADC值
        uint16_t adc_value = static_cast<uint16_t>(channel * 500);
        uint8_t high_byte = static_cast<uint8_t>((adc_value >> 8) & 0x0F);
        uint8_t low_byte = static_cast<uint8_t>(adc_value & 0xFF);
        std::vector<uint8_t> read_data = {high_byte, low_byte};
        m_bus->set_read_data(read_data);
        m_bus->set_read_result(HAS_OK);

        std::vector<uint8_t> in_buffer;
        std::vector<uint8_t> out_buffer;
        std::string error;

        int32_t result = m_chip->bit_read(channel, 2, 0, in_buffer, out_buffer, error);
        EXPECT_EQ(result, HAS_OK) << "Channel " << channel << " read failed";
        EXPECT_TRUE(error.empty()) << "Channel " << channel << " error: " << error;
        EXPECT_EQ(out_buffer.size(), 2) << "Channel " << channel << " output size incorrect";
    }
}

} // namespace

